/*-------------------------------------------------------------------------
 *
 * 前端代码的简单列表功能
 *
 * 简单OID和字符串列表的数据结构。与后端的List功能相比，这些支持非常原始，
 * 但在例如pg_dump中，我们需要这些功能。
 *
 *
 * Portions Copyright (c) 1996-2022, PostgreSQL Global Development Group
 * Portions Copyright (c) 1994, Regents of the University of California
 *
 * src/fe_utils/simple_list.c
 *
 *-------------------------------------------------------------------------
 */
#include "postgres_fe.h"

#include "fe_utils/simple_list.h"


/*
 * 将OID添加到列表中。
 */
void simple_oid_list_append(SimpleOidList *fc_list, Oid fc_val)
{
	SimpleOidListCell *fc_cell;

	fc_cell = (SimpleOidListCell *) pg_malloc(sizeof(SimpleOidListCell));
	fc_cell->next = NULL;
	fc_cell->val = fc_val;

	if (fc_list->tail)
		fc_list->tail->next = fc_cell;
	else
		fc_list->head = fc_cell;
	fc_list->tail = fc_cell;
}

/*
 * OID是否存在于列表中？
 */
bool simple_oid_list_member(SimpleOidList *fc_list, Oid fc_val)
{
	SimpleOidListCell *fc_cell;

	for (fc_cell = fc_list->head; fc_cell; fc_cell = fc_cell->next)
	{
		if (fc_cell->val == fc_val)
			return true;
	}
	return false;
}

/*
 * 将字符串添加到列表中。
 *
 * 给定的字符串会被复制，因此在调用后可以不再保留。
 */
void simple_string_list_append(SimpleStringList *fc_list, const char *fc_val)
{
	SimpleStringListCell *fc_cell;

	fc_cell = (SimpleStringListCell *)
		pg_malloc(offsetof(SimpleStringListCell, val) + strlen(fc_val) + 1);

	fc_cell->next = NULL;
	fc_cell->touched = false;
	strcpy(fc_cell->val, fc_val);

	if (fc_list->tail)
		fc_list->tail->next = fc_cell;
	else
		fc_list->head = fc_cell;
	fc_list->tail = fc_cell;
}

/*
 * 字符串是否存在于列表中？
 *
 * 如果找到，第一匹配项的“touched”字段将被设置为true。
 */
bool simple_string_list_member(SimpleStringList *fc_list, const char *fc_val)
{
	SimpleStringListCell *fc_cell;

	for (fc_cell = fc_list->head; fc_cell; fc_cell = fc_cell->next)
	{
		if (strcmp(fc_cell->val, fc_val) == 0)
		{
			fc_cell->touched = true;
			return true;
		}
	}
	return false;
}

/*
 * 销毁OID列表
 */
void simple_oid_list_destroy(SimpleOidList *fc_list)
{
	SimpleOidListCell *fc_cell;

	fc_cell = fc_list->head;
	while (fc_cell != NULL)
	{
		SimpleOidListCell *fc_next;

		fc_next = fc_cell->next;
		pg_free(fc_cell);
		fc_cell = fc_next;
	}
}

/*
 * 销毁字符串列表
 */
void simple_string_list_destroy(SimpleStringList *fc_list)
{
	SimpleStringListCell *fc_cell;

	fc_cell = fc_list->head;
	while (fc_cell != NULL)
	{
		SimpleStringListCell *fc_next;

		fc_next = fc_cell->next;
		pg_free(fc_cell);
		fc_cell = fc_next;
	}
}

/*
 * 查找第一个未被触及的列表项（如果存在）。
 */
const char * simple_string_list_not_touched(SimpleStringList *fc_list)
{
	SimpleStringListCell *fc_cell;

	for (fc_cell = fc_list->head; fc_cell; fc_cell = fc_cell->next)
	{
		if (!fc_cell->touched)
			return fc_cell->val;
	}
	return NULL;
}

/*
 * 将指针添加到列表中。
 *
 * 调用者必须确保指针保持有效。
 */
void simple_ptr_list_append(SimplePtrList *fc_list, void *fc_ptr)
{
	SimplePtrListCell *fc_cell;

	fc_cell = (SimplePtrListCell *) pg_malloc(sizeof(SimplePtrListCell));
	fc_cell->next = NULL;
	fc_cell->ptr = fc_ptr;

	if (fc_list->tail)
		fc_list->tail->next = fc_cell;
	else
		fc_list->head = fc_cell;
	fc_list->tail = fc_cell;
}
